home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 60 / IOPROG_60.ISO / soft / c++ / gsl-1.1.1-setup.exe / {app} / src / specfunc / bessel_j.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-18  |  10.7 KB  |  386 lines

  1. /* specfunc/bessel_j.c
  2.  * 
  3.  * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
  4.  * 
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or (at
  8.  * your option) any later version.
  9.  * 
  10.  * This program is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * General Public License for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. /* Author:  G. Jungman */
  21.  
  22. #include <config.h>
  23. #include <gsl/gsl_math.h>
  24. #include <gsl/gsl_errno.h>
  25. #include <gsl/gsl_sf_pow_int.h>
  26. #include <gsl/gsl_sf_trig.h>
  27. #include <gsl/gsl_sf_bessel.h>
  28.  
  29. #include "error.h"
  30.  
  31. #include "bessel.h"
  32. #include "bessel_olver.h"
  33.  
  34. /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
  35.  
  36. int gsl_sf_bessel_j0_e(const double x, gsl_sf_result * result)
  37. {
  38.   double ax = fabs(x);
  39.  
  40.   /* CHECK_POINTER(result) */
  41.  
  42.   if(ax < 0.5) {
  43.     const double y = x*x;
  44.     const double c1 = -1.0/6.0;
  45.     const double c2 =  1.0/120.0;
  46.     const double c3 = -1.0/5040.0;
  47.     const double c4 =  1.0/362880.0;
  48.     const double c5 = -1.0/39916800.0;
  49.     const double c6 =  1.0/6227020800.0;
  50.     result->val = 1.0 + y*(c1 + y*(c2 + y*(c3 + y*(c4 + y*(c5 + y*c6)))));
  51.     result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  52.     return GSL_SUCCESS;
  53.   }
  54.   else {
  55.     gsl_sf_result sin_result;
  56.     const int stat = gsl_sf_sin_e(x, &sin_result);
  57.     result->val  = sin_result.val/x;
  58.     result->err  = fabs(sin_result.err/x);
  59.     result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  60.     return stat;
  61.   }
  62. }
  63.  
  64.  
  65. int gsl_sf_bessel_j1_e(const double x, gsl_sf_result * result)
  66. {
  67.   double ax = fabs(x);
  68.  
  69.   /* CHECK_POINTER(result) */
  70.  
  71.   if(x == 0.0) {
  72.     result->val = 0.0;
  73.     result->err = 0.0;
  74.     return GSL_SUCCESS;
  75.   }
  76.   else if(ax < 3.1*GSL_DBL_MIN) {
  77.     UNDERFLOW_ERROR(result);
  78.   }
  79.   else if(ax < 0.25) {
  80.     const double y = x*x;
  81.     const double c1 = -1.0/10.0;
  82.     const double c2 =  1.0/280.0;
  83.     const double c3 = -1.0/15120.0;
  84.     const double c4 =  1.0/1330560.0;
  85.     const double c5 = -1.0/172972800.0;
  86.     const double sum = 1.0 + y*(c1 + y*(c2 + y*(c3 + y*(c4 + y*c5))));
  87.     result->val = x/3.0 * sum;
  88.     result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  89.     return GSL_SUCCESS;
  90.   }
  91.   else {
  92.     gsl_sf_result cos_result;
  93.     gsl_sf_result sin_result;
  94.     const int stat_cos = gsl_sf_cos_e(x, &cos_result);
  95.     const int stat_sin = gsl_sf_sin_e(x, &sin_result);
  96.     const double cos_x = cos_result.val;
  97.     const double sin_x = sin_result.val;
  98.     result->val  = (sin_x/x - cos_x)/x;
  99.     result->err  = (fabs(sin_result.err/x) + fabs(cos_result.err))/fabs(x);
  100.     result->err += 2.0 * GSL_DBL_EPSILON * (fabs(sin_x/(x*x)) + fabs(cos_x/x));
  101.     result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  102.     return GSL_ERROR_SELECT_2(stat_cos, stat_sin);
  103.   }
  104. }
  105.  
  106.  
  107. int gsl_sf_bessel_j2_e(const double x, gsl_sf_result * result)
  108. {
  109.   double ax = fabs(x);
  110.  
  111.   /* CHECK_POINTER(result) */
  112.   
  113.   if(x == 0.0) {
  114.     result->val = 0.0;
  115.     result->err = 0.0;
  116.     return GSL_SUCCESS;
  117.   }
  118.   else if(ax < 4.0*GSL_SQRT_DBL_MIN) {
  119.     UNDERFLOW_ERROR(result);
  120.   }
  121.   else if(ax < 1.3) {
  122.     const double y  = x*x;
  123.     const double c1 = -1.0/14.0;
  124.     const double c2 =  1.0/504.0;
  125.     const double c3 = -1.0/33264.0;
  126.     const double c4 =  1.0/3459456.0;
  127.     const double c5 = -1.0/518918400;
  128.     const double c6 =  1.0/105859353600.0;
  129.     const double c7 = -1.0/28158588057600.0;
  130.     const double c8 =  1.0/9461285587353600.0;
  131.     const double c9 = -1.0/3916972233164390400.0;
  132.     const double sum = 1.0+y*(c1+y*(c2+y*(c3+y*(c4+y*(c5+y*(c6+y*(c7+y*(c8+y*c9))))))));
  133.     result->val = y/15.0 * sum;
  134.     result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  135.     return GSL_SUCCESS;
  136.   }
  137.   else {
  138.     gsl_sf_result cos_result;
  139.     gsl_sf_result sin_result;
  140.     const int stat_cos = gsl_sf_cos_e(x, &cos_result);
  141.     const int stat_sin = gsl_sf_sin_e(x, &sin_result);
  142.     const double cos_x = cos_result.val;
  143.     const double sin_x = sin_result.val;
  144.     const double f = (3.0/(x*x) - 1.0);
  145.     result->val  = (f * sin_x - 3.0*cos_x/x)/x;
  146.     result->err  = fabs(f * sin_result.err/x) + fabs((3.0*cos_result.err/x)/x);
  147.     result->err += 2.0 * GSL_DBL_EPSILON * (fabs(f*sin_x/x) + 3.0*fabs(cos_x/(x*x)));
  148.     result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  149.     return GSL_ERROR_SELECT_2(stat_cos, stat_sin);
  150.   }
  151. }
  152.  
  153.  
  154. int
  155. gsl_sf_bessel_jl_e(const int l, const double x, gsl_sf_result * result)
  156. {
  157.   if(l < 0 || x < 0.0) {
  158.     DOMAIN_ERROR(result);
  159.   }
  160.   else if(x == 0.0) {
  161.     result->val = ( l > 0 ? 0.0 : 1.0 );
  162.     result->err = 0.0;
  163.     return GSL_SUCCESS;
  164.   }
  165.   else if(l == 0) {
  166.     return gsl_sf_bessel_j0_e(x, result);
  167.   }
  168.   else if(l == 1) {
  169.     return gsl_sf_bessel_j1_e(x, result);
  170.   }
  171.   else if(l == 2) {
  172.     return gsl_sf_bessel_j2_e(x, result);
  173.   }
  174.   else if(x*x < 10.0*(l+0.5)/M_E) {
  175.     gsl_sf_result b;
  176.     int status = gsl_sf_bessel_IJ_taylor_e(l+0.5, x, -1, 50, GSL_DBL_EPSILON, &b);
  177.     double pre   = sqrt((0.5*M_PI)/x);
  178.     result->val  = pre * b.val;
  179.     result->err  = pre * b.err;
  180.     result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  181.     return status;
  182.   }
  183.   else if(GSL_ROOT3_DBL_EPSILON * x > (l*l + l + 1.0)) {
  184.     gsl_sf_result b;
  185.     int status = gsl_sf_bessel_Jnu_asympx_e(l + 0.5, x, &b);
  186.     double pre = sqrt((0.5*M_PI)/x);
  187.     result->val = pre * b.val;
  188.     result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val) + pre * b.err;
  189.     return status;
  190.   }
  191.   else if(l > 1.0/GSL_ROOT6_DBL_EPSILON) {
  192.     gsl_sf_result b;
  193.     int status = gsl_sf_bessel_Jnu_asymp_Olver_e(l + 0.5, x, &b);
  194.     double pre = sqrt((0.5*M_PI)/x);
  195.     result->val = pre * b.val;
  196.     result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val) + pre * b.err;
  197.     return status;
  198.   }
  199.   else {
  200.     double sgn;
  201.     double ratio;
  202.     int stat_CF1 = gsl_sf_bessel_J_CF1(l+0.5, x, &ratio, &sgn);
  203.     double jellp1 = GSL_SQRT_DBL_EPSILON * ratio;
  204.     double jell   = GSL_SQRT_DBL_EPSILON;
  205.     double jellm1;
  206.     int ell;
  207.     for(ell = l; ell > 0; ell--) {
  208.       jellm1 = -jellp1 + (2*ell + 1)/x * jell;
  209.       jellp1 = jell;
  210.       jell   = jellm1;
  211.     }
  212.  
  213.     if(fabs(jell) > fabs(jellp1)) {
  214.       gsl_sf_result j0_result;
  215.       int stat_j0  = gsl_sf_bessel_j0_e(x, &j0_result);
  216.       double pre   = GSL_SQRT_DBL_EPSILON / jell;
  217.       result->val  = j0_result.val * pre;
  218.       result->err  = j0_result.err * fabs(pre);
  219.       result->err += 2.0 * GSL_DBL_EPSILON * (0.5*l + 1.0) * fabs(result->val);
  220.       return GSL_ERROR_SELECT_2(stat_j0, stat_CF1);
  221.     }
  222.     else {
  223.       gsl_sf_result j1_result;
  224.       int stat_j1  = gsl_sf_bessel_j1_e(x, &j1_result);
  225.       double pre   = GSL_SQRT_DBL_EPSILON / jellp1;
  226.       result->val  = j1_result.val * pre;
  227.       result->err  = j1_result.err * fabs(pre);
  228.       result->err += 2.0 * GSL_DBL_EPSILON * (0.5*l + 1.0) * fabs(result->val);
  229.       return GSL_ERROR_SELECT_2(stat_j1, stat_CF1);
  230.     }
  231.   }
  232. }
  233.  
  234.  
  235. int
  236. gsl_sf_bessel_jl_array(const int lmax, const double x, double * result_array)
  237. {
  238.   /* CHECK_POINTER(result_array) */
  239.  
  240.   if(lmax < 0 || x < 0.0) {
  241.     int j;
  242.     for(j=0; j<=lmax; j++) result_array[j] = 0.0;
  243.     GSL_ERROR ("error", GSL_EDOM);
  244.   }
  245.   else if(x == 0.0) {
  246.     int j;
  247.     for(j=1; j<=lmax; j++) result_array[j] = 0.0;
  248.     result_array[0] = 1.0;
  249.     return GSL_SUCCESS;
  250.   }
  251.   else {
  252.     gsl_sf_result r_jellp1;
  253.     gsl_sf_result r_jell;
  254.     int stat_0 = gsl_sf_bessel_jl_e(lmax+1, x, &r_jellp1);
  255.     int stat_1 = gsl_sf_bessel_jl_e(lmax,   x, &r_jell);
  256.     double jellp1 = r_jellp1.val;
  257.     double jell   = r_jell.val;
  258.     double jellm1;
  259.     int ell;
  260.  
  261.     result_array[lmax] = jell;
  262.     for(ell = lmax; ell >= 1; ell--) {
  263.       jellm1 = -jellp1 + (2*ell + 1)/x * jell;
  264.       jellp1 = jell;
  265.       jell   = jellm1;
  266.       result_array[ell-1] = jellm1;
  267.     }
  268.  
  269.     return GSL_ERROR_SELECT_2(stat_0, stat_1);
  270.   }
  271. }
  272.  
  273.  
  274. int gsl_sf_bessel_jl_steed_array(const int lmax, const double x, double * jl_x)
  275. {
  276.   /* CHECK_POINTER(jl_x) */
  277.  
  278.   if(lmax < 0 || x < 0.0) {
  279.     int j;
  280.     for(j=0; j<=lmax; j++) jl_x[j] = 0.0;
  281.     GSL_ERROR ("error", GSL_EDOM);
  282.   }
  283.   else if(x == 0.0) {
  284.     int j;
  285.     for(j=1; j<=lmax; j++) jl_x[j] = 0.0;
  286.     jl_x[0] = 1.0;
  287.     return GSL_SUCCESS;
  288.   }
  289.   else if(x < 2.0*GSL_ROOT4_DBL_EPSILON) {
  290.     /* first two terms of Taylor series */
  291.     double inv_fact = 1.0;  /* 1/(1 3 5 ... (2l+1)) */
  292.     double x_l      = 1.0;  /* x^l */
  293.     int l;
  294.     for(l=0; l<=lmax; l++) {
  295.       jl_x[l]  = x_l * inv_fact;
  296.       jl_x[l] *= 1.0 - 0.5*x*x/(2.0*l+3.0);
  297.       inv_fact /= 2.0*l+3.0;
  298.       x_l      *= x;
  299.     }
  300.     return GSL_SUCCESS;
  301.   }
  302.   else {
  303.     /* Steed/Barnett algorithm [Comp. Phys. Comm. 21, 297 (1981)] */
  304.     double x_inv = 1.0/x;
  305.     double W = 2.0*x_inv;
  306.     double F = 1.0;
  307.     double FP = (lmax+1.0) * x_inv;
  308.     double B = 2.0*FP + x_inv;
  309.     double end = B + 20000.0*W;
  310.     double D = 1.0/B;
  311.     double del = -D;
  312.     
  313.     FP += del;
  314.     
  315.     /* continued fraction */
  316.     do {
  317.       B += W;
  318.       D = 1.0/(B-D);
  319.       del *= (B*D - 1.);
  320.       FP += del;
  321.       if(D < 0.0) F = -F;
  322.       if(B > end) {
  323.     GSL_ERROR ("error", GSL_EMAXITER);
  324.       }
  325.     }
  326.     while(fabs(del) >= fabs(FP) * GSL_DBL_EPSILON);
  327.     
  328.     FP *= F;
  329.     
  330.     if(lmax > 0) {
  331.       /* downward recursion */
  332.       double XP2 = FP;
  333.       double PL = lmax * x_inv;
  334.       int L  = lmax;
  335.       int LP;
  336.       jl_x[lmax] = F;
  337.       for(LP = 1; LP<=lmax; LP++) {
  338.     jl_x[L-1] = PL * jl_x[L] + XP2;
  339.     FP = PL*jl_x[L-1] - jl_x[L];
  340.     XP2 = FP;
  341.     PL -= x_inv;
  342.     --L;
  343.       }
  344.       F = jl_x[0];
  345.     }
  346.     
  347.     /* normalization */
  348.     W = x_inv / sqrt(FP*FP + F*F);
  349.     jl_x[0] = W*F;
  350.     if(lmax > 0) {
  351.       int L;
  352.       for(L=1; L<=lmax; L++) {
  353.     jl_x[L] *= W;
  354.       }
  355.     }
  356.  
  357.     return GSL_SUCCESS;
  358.   }
  359. }
  360.  
  361.  
  362. /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
  363.  
  364. #include "eval.h"
  365.  
  366. double gsl_sf_bessel_j0(const double x)
  367. {
  368.   EVAL_RESULT(gsl_sf_bessel_j0_e(x, &result));
  369. }
  370.  
  371. double gsl_sf_bessel_j1(const double x)
  372. {
  373.   EVAL_RESULT(gsl_sf_bessel_j1_e(x, &result));
  374. }
  375.  
  376. double gsl_sf_bessel_j2(const double x)
  377. {
  378.   EVAL_RESULT(gsl_sf_bessel_j2_e(x, &result));
  379. }
  380.  
  381. double gsl_sf_bessel_jl(const int l, const double x)
  382. {
  383.   EVAL_RESULT(gsl_sf_bessel_jl_e(l, x, &result));
  384. }
  385.  
  386.